﻿#pragma once
#include "AsQBasicGlobal.h"
#include "AsCatcher.h"

namespace AsMath {

	template<typename _Type>
	_Type accumulate(const QVector<_Type>& array) {
		_Type ret = 0;
		for (auto i = array.begin(); i != array.end(); i++) {
			ret += *i;
		}
		return ret;
	}

	template<typename _Type>
	_Type mean(const QVector<_Type>& array) {
		if (array.empty()) return 0;
		_Type ret = AsMath::accumulate(array) / array.size();
		return ret;
	}

	template<typename _Type>
	_Type stddev(const QVector<_Type>& array) {
		if (array.size() < 2) return 0;
		_Type mean_val = AsMath::mean(array);
		_Type ret = 0;
		for (auto i = array.begin(); i != array.end(); i++) {
			ret += (*i - mean_val) * (*i - mean_val);
		}
		return sqrt(ret / (array.size() - 1));
	}

	template<typename _Type>
	_Type stddev(const QVector<_Type>& array, _Type mean_val) {
		if (array.size() < 2) return 0;
		_Type ret = 0;
		for (auto i = array.begin(); i != array.end(); i++) {
			ret += (*i - mean_val) * (*i - mean_val);
		}
		return sqrt(ret / array.size() - 1);
	}

	template<typename _Type>
	void operate_linear(const QVector<_Type>& input, QVector<_Type>& output, _Type alpha, _Type beta) {
		output.resize(input.size());
		auto i = input.begin();
		auto j = output.begin();
		for (; i != input.end(); i++, j++) {
			*j = alpha * (*i) + beta;
		}
	}

	template<typename _Type>
	_Type maximum(const QVector<_Type>& input) {
		asCatcher(IsEmpty(input), return _Type());
		_Type ret = input.front();
		for (auto i = input.begin(); i != input.end(); i++) {
			if (ret < *i) ret = *i;
		}
		return ret;
	}

	template<typename _Type>
	_Type minimum(const QVector<_Type>& input) {
		asCatcher(IsEmpty(input), return _Type());
		_Type ret = input.front();
		for (auto i = input.begin(); i != input.end(); i++) {
			if (ret > *i) ret = *i;
		}
		return ret;
	}

	template<typename _Type>
	QVector<_Type>& sort(QVector<_Type>& input) {
		for (auto i = input.begin(); i != input.end(); i++) {
			for (auto j = i + 1; j != input.end(); j++) {
				if (*i > *j) {
					_Type t = *i;
					*i = *j;
					*j = t;
				}
			}
		}
		return input;
	}


};

